﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Collections.Specialized;
using System.Data.Objects;

namespace Doo.DataClass
{

    #region 基础实体

    /// <summary>
    /// 数据上下文提供者
    /// </summary>
    /// <typeparam name="TEntities"></typeparam>
    public abstract class EntitiesProvider<TEntities> where TEntities : ObjectContext
    {
        protected static EntitiesProvider<TEntities> instance;

        /// <summary>
        /// 获取已经初始化的上下文
        /// </summary>
        /// <returns></returns>
        public static TEntities GetEntities()
        {
            if (instance == null) throw new Exception("尚未初始化");
            return instance.GetEntitiesIns();
        }

        /// <summary>
        /// 初始化上下文
        /// </summary>
        /// <param name="provider"></param>
        public static void InitEntities(EntitiesProvider<TEntities> provider)
        {
            instance = provider;
        }

        /// <summary>
        /// 获取上下文实例
        /// </summary>
        /// <returns></returns>
        public abstract TEntities GetEntitiesIns();

    }

    /// <summary>
    /// 数据类的基类
    /// </summary>
    /// <typeparam name="TEntities"></typeparam>
    public class DataClassBase<TEntities> where TEntities : ObjectContext
    {
        /// <summary>
        /// 获取实体集
        /// </summary>
        /// <returns></returns>
        public TEntities GetEntities()
        {
            return EntitiesProvider<TEntities>.GetEntities();
        }

        /// <summary>
        /// 是否允许缓存
        /// </summary>
        public virtual bool EnableCache { get; set; }

        /// <summary>
        /// 获取缓存帮助对象
        /// </summary>
        /// <returns></returns>
        public virtual ICacheHelper GetCacheHelper() { return null; }
    }

    #endregion

    #region 数据获取

    /// <summary>
    /// 可分页接口
    /// </summary>
    public interface IPageable
    {
        int RowStart { get; set; }
        int RowCount { get; set; }
        int PageIndex { get; set; }
        int PageSize { get; set; }
        int TotalRecordCount { get; }
    }

    /// <summary>
    /// 返回数据类型
    /// </summary>
    public class ListClassReturnType
    {
        public const string Array = "array";
        public const string List = "list";
        public const string Record = "rec";
    }

    /// <summary>
    /// 列表数据类，支持缓存
    /// </summary>
    /// <typeparam name="TEntities"></typeparam>
    /// <typeparam name="TEntity"></typeparam>
    public abstract class ListClass<TEntities, TEntity> : DataClassBase<TEntities>, IPageable
        where TEntities : ObjectContext
        where TEntity : class, new()
    {
        #region 分页相关

        private int rowstart;

        private int rowcount = 100;

        private int pageindex;

        /// <summary>
        /// 起始行数（从0开始）
        /// </summary>
        public int RowStart
        {
            get { return pageindex < 1 ? rowstart : (pageindex - 1) * rowcount; }
            set { rowstart = value; }
        }

        /// <summary>
        /// 本次要取的行数
        /// </summary>
        public int RowCount
        {
            get { return rowcount; }
            set { rowcount = value; }
        }

        /// <summary>
        /// 每页个数
        /// </summary>
        public int PageSize
        {
            get { return rowcount; }
            set { rowcount = value; }
        }

        /// <summary>
        /// 页码【从1开始】
        /// </summary>
        public int PageIndex
        {
            get { return pageindex; }
            set { pageindex = value; }
        }

        private int _totalRecordCount;
        /// <summary>
        /// 符合条件的记录总条数
        /// </summary>
        public int TotalRecordCount { get { return _totalRecordCount; } }

        private bool _autoGetTotalRecordCount = true;
        /// <summary>
        /// 是否自动获取总记录数，默认为True
        /// </summary>
        public bool AutoGetTotalRecordCount
        {
            get { return _autoGetTotalRecordCount; }
            set { _autoGetTotalRecordCount = value; }
        }

        #endregion

        private string _lastDataVersion;
        /// <summary>
        /// 获取上次数据版本号
        /// </summary>
        public string LastDataVersion
        {
            get
            {
                if (_lastDataVersion == null)
                {
                    _lastDataVersion = Doo.Extension.VersionCache.GetVersion(_lastCacheKey);
                }
                return _lastDataVersion;
            }
        }

        /// <summary>
        /// 得到查询
        /// </summary>
        /// <param name="container"></param>
        /// <returns></returns>
        public abstract IOrderedQueryable<TEntity> GetQuery(TEntities container);

        #region 缓存处理

        /// <summary>
        /// 如果开启了缓存，必须重载此方法
        /// 返回标识此记录集的键值，例如RecordID
        /// </summary>
        /// <returns></returns>
        public virtual string GetCacheKeyValue()
        {
            throw new NotImplementedException("要使用缓存功能，需要重载GetCacheKeyValue方法以获取标识结果的依赖值来创建缓存依赖，如都是属于某个Code的记录集");
        }

        /// <summary>
        /// 返回标识该记录集的筛选信息
        /// </summary>
        /// <returns></returns>
        public virtual string GetCacheInfo()
        {
            return string.Empty;
        }

        /// <summary>
        /// 此属性用于标识数据类型。
        /// </summary>
        string CacheKey
        {
            get
            {
                return typeof(TEntity).Name;
            }
        }

        /// <summary>
        /// 一次缓存处理过程
        /// </summary>
        string _lastKeyValue;

        string _lastCacheKey;

        /// <summary>
        /// 上次数据获取产生的缓存键
        /// </summary>
        public string LastCacheKey
        {
            get
            {
                return _lastCacheKey;
            }
        }

        #region 创建要设置的缓存键值

        string _CreateCacheKey(string plus)
        {
            _lastCacheKey = GetCacheHelper().CreateCacheKey(GetCacheKeyValue(), GetCacheInfo() + plus + "_" + RowStart + "_" + RowCount);
            return _lastCacheKey;
        }

        /// <summary>
        /// 创建一个缓存键
        /// </summary>
        /// <param name="dataType"></param>
        /// <returns></returns>
        public string CreateCacheKey(string dataType)
        {
            return _CreateCacheKey(typeof(TEntity).Name + "$" + dataType);
        }

        /// <summary>
        /// 创建一个缓存键
        /// </summary>
        public string CreateCacheKey<Td>(string dataType)
        {
            return _CreateCacheKey(typeof(Td).Name + "$" + dataType);
        }

        /// <summary>
        /// 创建一个缓存键
        /// </summary>
        public string CreateCacheKey<Td, TSelector>(string dataType)
        {
            return _CreateCacheKey(typeof(Td).Name + "$" + typeof(TSelector).Name + "$" + dataType);
        }

        #endregion

        #region 获取缓存中的数据版本

        /// <summary>
        /// 获取缓存版本，如果是要获取刚刚取出数据的版本号，使用DataVersion属性即可
        /// </summary>
        /// <returns></returns>
        public string GetCacheVersion(string datatype)
        {
            string ck = CreateCacheKey(datatype);
            return Doo.Extension.VersionCache.GetVersion(ck);
        }

        /// <summary>
        /// 获取缓存版本，如果是要获取刚刚取出数据的版本号，使用DataVersion属性即可
        /// </summary>
        /// <returns></returns>
        public string GetCacheVersion<Td>(string datatype)
        {
            string ck = CreateCacheKey<Td>(datatype);
            return Doo.Extension.VersionCache.GetVersion(ck);
        }

        /// <summary>
        /// 获取缓存版本，如果是要获取刚刚取出数据的版本号，使用DataVersion属性即可
        /// </summary>
        /// <returns></returns>
        public string GetCacheVersion<Td, TSelector>(string datatype)
        {
            string ck = CreateCacheKey<Td, TSelector>(datatype);
            return Doo.Extension.VersionCache.GetVersion(ck);
        }

        #endregion

        #endregion

        #region 各种方法

        #region 原类型

        /* 采用container的方法不适用缓存，因为缓存中的数据与container无关联 */

        /// <summary>
        /// 获取缓存的数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="Td"></typeparam>
        /// <param name="returnType"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        T GetCachedData<T, Td>(string returnType, Func<object> func) where T : class
        {
            _lastKeyValue = GetCacheKeyValue();
            if (typeof(Td) == typeof(TEntity))
            {
                CreateCacheKey(returnType);
            }
            else
            {
                CreateCacheKey<Td>(returnType);
            }
            return _GetCachedData<T>(func);
        }

        T GetCachedData<T, Td, TSelector>(string returnType, Func<object> func) where T : class
        {
            _lastKeyValue = GetCacheKeyValue();
            CreateCacheKey<Td, TSelector>(returnType);
            return _GetCachedData<T>(func);
        }

        /// <summary>
        /// 被其他方法调用，且必须先用CreateCacheKey
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <returns></returns>
        private T _GetCachedData<T>(Func<object> func) where T : class
        {
            var helper = GetCacheHelper();
            if (helper.HasFullKey(_lastCacheKey))
            {
                //缓存中有这个值
                T data = helper.Get(_lastCacheKey) as T;
                if (data == null) _totalRecordCount = 0;
                else if (AutoGetTotalRecordCount)
                {
                    _totalRecordCount = _GetCachedCount();
                    if (_totalRecordCount == -1)
                    {
                        //还是没有找到
                        using (var container = GetEntities())
                        {
                            _totalRecordCount = GetQuery(container).Count();
                        }
                    }
                }
                return data;
            }
            else
            {
                //缓存中没有这个值
                T data = func() as T;
                //如果允许缓存，则创建依赖
                helper.Set(_lastCacheKey, data, _lastKeyValue);
                EntityCacheHelper.Instance.RegisterTypeFieldsIfNot<TEntity, T>();
                EntityCacheHelper.Instance.RegisterEntityDepend<TEntity>(this, _lastCacheKey, data);
                Doo.Extension.VersionCache.UpdateVersion(_lastCacheKey);
                _lastDataVersion = Doo.Extension.VersionCache.GetVersion(_lastCacheKey);
                return data;
            }
        }


        /// <summary>
        /// 获取缓存中的列表长度
        /// </summary>
        /// <returns></returns>
        int _GetCachedCount()
        {
            var helper = GetCacheHelper();
            string ck = helper.CreateCacheKey(_lastKeyValue, GetCacheInfo() + CacheKey + "$c");
            object c = helper.Get(ck);
            return c == null ? -1 : (int)c;
        }

        /// <summary>
        /// 获取列表长度
        /// </summary>
        /// <param name="ck"></param>
        /// <returns></returns>
        int GetCachedCount(string ck, string keyvalue)
        {
            if (keyvalue == null) keyvalue = GetCacheKeyValue();
            object c = GetCacheHelper().Get(keyvalue, ck);
            if (c == null) return -1;
            return (int)c;
        }

        int _GetCount(IOrderedQueryable<TEntity> query)
        {
            if (EnableCache)
            {
                string ck = GetCacheInfo() + CacheKey + "$c";
                _lastKeyValue = GetCacheKeyValue();
                _totalRecordCount = GetCachedCount(ck, _lastKeyValue);
                if (_totalRecordCount == -1)
                {
                    _totalRecordCount = query.Count();
                    EntityCacheHelper.Instance.RegisterEntityDepend<TEntity>(this, _lastCacheKey, _totalRecordCount);
                    GetCacheHelper().Set(_lastKeyValue, ck, _totalRecordCount);
                }
                return _totalRecordCount;
            }
            else
            {
                _totalRecordCount = query.Count();
                return _totalRecordCount;
            }
        }

        /// <summary>
        /// 获取满足条件的记录数
        /// </summary>
        /// <param name="container"></param>
        /// <returns></returns>
        public int GetCount(TEntities container)
        {
            var query = GetQuery(container);
            return _GetCount(query);
        }

        /// <summary>
        /// 获取满足条件的记录数
        /// </summary>
        /// <returns></returns>
        public int GetCount()
        {
            using (var container = GetEntities())
            {
                return GetCount(container);
            }
        }

        public List<TEntity> GetList(TEntities container)
        {
            var query = GetQuery(container);
            if (AutoGetTotalRecordCount) _GetCount(query);
            return query.Skip(RowStart).Take(RowCount).ToList();
        }

        List<TEntity> _GetList()
        {
            using (var container = GetEntities())
            {
                return GetList(container);
            }
        }

        /// <summary>
        /// 根据给定的条件获取一个列表
        /// </summary>
        /// <returns></returns>
        public List<TEntity> GetList()
        {
            return EnableCache
                ? GetCachedData<List<TEntity>, TEntity>(ListClassReturnType.List, _GetList)
                : _GetList();
        }

        public List<TResult> GetList<TResult>(TEntities container, System.Linq.Expressions.Expression<Func<TEntity, TResult>> selector)
        {
            var query = GetQuery(container);
            if (AutoGetTotalRecordCount) _GetCount(query);
            return query.Select(selector).Skip(RowStart).Take(RowCount).ToList();
        }

        /// <summary>
        /// 根据给定的条件和选择语句获取一个列表
        /// </summary>
        /// <param name="selector">自定义选择语句</param>
        /// <returns></returns>
        public List<TResult> GetList<TResult>(System.Linq.Expressions.Expression<Func<TEntity, TResult>> selector)
        {
            using (var container = GetEntities())
            {
                return GetList(container, selector);

            }
        }

        public TEntity[] GetArray(TEntities container)
        {
            var query = GetQuery(container);
            if (AutoGetTotalRecordCount) _GetCount(query);
            return query.Skip(RowStart).Take(RowCount).ToArray();
        }

        TEntity[] _GetArray()
        {
            using (var container = GetEntities())
            {
                return GetArray(container);
            }
        }

        public TResult[] GetArray<TResult>(TEntities container, System.Linq.Expressions.Expression<Func<TEntity, TResult>> selector)
        {
            var query = GetQuery(container);
            if (AutoGetTotalRecordCount) _GetCount(query);
            return query.Select(selector).Skip(RowStart).Take(RowCount).ToArray();
        }

        public TResult[] GetArray<TResult>(System.Linq.Expressions.Expression<Func<TEntity, TResult>> selector)
        {
            using (var container = GetEntities())
            {
                return GetArray(container, selector);

            }
        }

        /// <summary>
        /// 根据给定的条件获取一个数组
        /// </summary>
        /// <returns></returns>
        public TEntity[] GetArray()
        {
            return EnableCache
                ? GetCachedData<TEntity[], TEntity>(ListClassReturnType.Array, _GetArray)
                : _GetArray();
        }

        public TEntity GetFirstOrDefault(TEntities container)
        {
            var query = GetQuery(container);
            var rec = query.FirstOrDefault();
            _totalRecordCount = rec == null ? 0 : 1;
            return rec;
        }

        TEntity _GetFirstOrDefault()
        {
            using (var container = GetEntities())
            {
                return GetFirstOrDefault(container);
            }
        }

        public TEntity GetFirstOrDefault()
        {
            return EnableCache
                ? GetCachedData<TEntity, TEntity>(ListClassReturnType.Record, _GetFirstOrDefault)
                : _GetFirstOrDefault();
        }

        //对于可变函数也不使用缓存，因为很难获取缓存键

        public TResult GetFirstOrDefault<TResult>(TEntities container, System.Linq.Expressions.Expression<Func<TEntity, TResult>> selector)
        {
            var query = GetQuery(container).Select(selector);
            var obj = query.FirstOrDefault();
            _totalRecordCount = obj == null ? 0 : 1;
            return obj;
        }

        /// <summary>
        /// 取得查询中的第一个元素
        /// </summary>
        /// <param name="selector">投影函数</param>
        /// <returns></returns>
        public TResult GetFirstOrDefault<TResult>(System.Linq.Expressions.Expression<Func<TEntity, TResult>> selector)
        {
            using (var container = GetEntities())
            {
                return GetFirstOrDefault(container, selector);
            }
        }

        #endregion

        #region 指定类型

        #region 公用

        protected List<Td> GetList<Td>(TEntities container, Func<IOrderedQueryable<TEntity>, IOrderedQueryable<Td>> selector)
        {
            var query = GetQuery(container);
            IOrderedQueryable<Td> queryFinal = selector(query);
            //此处用CacheKey的原因是在设计中selector不会对集合做出记录筛选。如果要筛选，则应改用筛选类型名。
            if (AutoGetTotalRecordCount) _GetCount(query);
            return queryFinal.Skip(RowStart).Take(RowCount).ToList();
        }

        protected Td[] GetArray<Td>(TEntities container, Func<IOrderedQueryable<TEntity>, IOrderedQueryable<Td>> selector)
        {
            var query = GetQuery(container);
            IOrderedQueryable<Td> queryFinal = selector(query);
            if (AutoGetTotalRecordCount) _GetCount(query);
            return queryFinal.Skip(RowStart).Take(RowCount).ToArray();
        }

        protected Td GetFirstOrDefault<Td>(TEntities container, Func<IOrderedQueryable<TEntity>, IOrderedQueryable<Td>> selector)
        {
            var query = GetQuery(container);
            IOrderedQueryable<Td> queryFinal = selector(query);
            _totalRecordCount = 1;
            return queryFinal.FirstOrDefault();
        }


        #endregion

        #region 指定类型，自带选择器

        public List<Td> GetList<Td>(TEntities container) where Td : CustomEntity<TEntity, Td>
        {
            return GetList<Td>(container, CustomEntity<TEntity, Td>.Selector);
        }

        List<Td> _GetList<Td>() where Td : CustomEntity<TEntity, Td>
        {
            using (var container = GetEntities())
            {
                return GetList<Td>(container, CustomEntity<TEntity, Td>.Selector);
            }
        }

        public List<Td> GetList<Td>() where Td : CustomEntity<TEntity, Td>
        {
            return EnableCache
                ? GetCachedData<List<Td>, Td>(ListClassReturnType.List, _GetList<Td>)
                : _GetList<Td>();
        }

        public Td[] GetArray<Td>(TEntities container) where Td : CustomEntity<TEntity, Td>
        {
            return GetArray<Td>(container, CustomEntity<TEntity, Td>.Selector);
        }

        Td[] _GetArray<Td>() where Td : CustomEntity<TEntity, Td>
        {
            using (var container = GetEntities())
            {
                return GetArray<Td>(container, CustomEntity<TEntity, Td>.Selector);
            }
        }

        public Td[] GetArray<Td>() where Td : CustomEntity<TEntity, Td>
        {
            return EnableCache
                ? GetCachedData<Td[], Td>(ListClassReturnType.Array, _GetArray<Td>)
                : _GetArray<Td>();
        }

        public Td GetFirstOrDefault<Td>(TEntities container) where Td : CustomEntity<TEntity, Td>
        {
            return GetFirstOrDefault<Td>(container, CustomEntity<TEntity, Td>.Selector);
        }

        Td _GetFirstOrDefault<Td>() where Td : CustomEntity<TEntity, Td>
        {
            using (var container = GetEntities())
            {
                return GetFirstOrDefault<Td>(container, CustomEntity<TEntity, Td>.Selector);
            }
        }

        public Td GetFirstOrDefault<Td>() where Td : CustomEntity<TEntity, Td>
        {
            return EnableCache
                ? GetCachedData<Td, Td>(ListClassReturnType.Record, _GetFirstOrDefault<Td>)
                : _GetFirstOrDefault<Td>();
        }

        #endregion

        #region 指定类型和选择器

        public List<Td> GetList<Td, TSelector>(TEntities container) where TSelector : CustomEntity<TEntity, Td>
        {
            var selector = CustomEntity<TEntity, Td>.GetSelector(typeof(TSelector));
            return GetList<Td>(container, selector);
        }

        /// <summary>
        /// 获取一个列表
        /// </summary>
        /// <typeparam name="Td">目标类型</typeparam>
        /// <typeparam name="TSelector">选择器类型</typeparam>
        /// <returns></returns>
        List<Td> _GetList<Td, TSelector>() where TSelector : CustomEntity<TEntity, Td>
        {
            using (var container = GetEntities())
            {
                return GetList<Td, TSelector>(container);
            }
        }
        public List<Td> GetList<Td, TSelector>() where TSelector : CustomEntity<TEntity, Td>
        {
            return EnableCache
                ? GetCachedData<List<Td>, Td, TSelector>(ListClassReturnType.List, _GetList<Td, TSelector>)
                : _GetList<Td, TSelector>();
        }
        public Td[] GetArray<Td, TSelector>(TEntities container) where TSelector : CustomEntity<TEntity, Td>
        {
            var selector = CustomEntity<TEntity, Td>.GetSelector(typeof(TSelector));
            return GetArray<Td>(container, selector);
        }

        Td[] _GetArray<Td, TSelector>() where TSelector : CustomEntity<TEntity, Td>
        {
            using (var container = GetEntities())
            {
                return GetArray<Td, TSelector>(container);
            }
        }

        public Td[] GetArray<Td, TSelector>() where TSelector : CustomEntity<TEntity, Td>
        {
            return EnableCache
                ? GetCachedData<Td[], Td, TSelector>(ListClassReturnType.Array, _GetArray<Td, TSelector>)
                : _GetArray<Td, TSelector>();
        }

        public Td GetFirstOrDefault<Td, TSelector>(TEntities container) where TSelector : CustomEntity<TEntity, Td>
        {
            var selector = CustomEntity<TEntity, Td>.GetSelector(typeof(TSelector));
            return GetFirstOrDefault<Td>(container, selector);
        }

        Td _GetFirstOrDefault<Td, TSelector>()
            where TSelector : CustomEntity<TEntity, Td>
            where Td : class
        {
            using (var container = GetEntities())
            {
                return GetFirstOrDefault<Td, TSelector>(container);
            }
        }

        /// <summary>
        /// 获取满足条件的第一条记录
        /// </summary>
        /// <typeparam name="Td"></typeparam>
        /// <typeparam name="TSelector"></typeparam>
        /// <returns></returns>
        public Td GetFirstOrDefault<Td, TSelector>()
            where TSelector : CustomEntity<TEntity, Td>
            where Td : class
        {
            return EnableCache
                ? GetCachedData<Td, Td, TSelector>(ListClassReturnType.Record, _GetFirstOrDefault<Td, TSelector>)
                : _GetFirstOrDefault<Td, TSelector>();
        }

        #endregion

        #endregion

        #endregion
    }

    /// <summary>
    /// 用于从数据库获取自定义数据的自定义类
    /// </summary>
    /// <typeparam name="Ts">数据类</typeparam>
    /// <typeparam name="Td">自定义类</typeparam>
    public abstract class CustomEntity<Ts, Td>
    {
        /// <summary>
        /// 在派生类中重写以获取选择器
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        protected abstract IOrderedQueryable<Td> GetSelector(IOrderedQueryable<Ts> source);

        #region 缓存的各种Func

        protected static Hashtable selectorByType = new Hashtable();

        public static Func<IOrderedQueryable<Ts>, IOrderedQueryable<Td>> GetSelector(Type T)
        {
            var selector = selectorByType[T] as Func<IOrderedQueryable<Ts>, IOrderedQueryable<Td>>;
            if (selector == null)
            {
                selector = new Func<IOrderedQueryable<Ts>, IOrderedQueryable<Td>>((Activator.CreateInstance(T) as CustomEntity<Ts, Td>).GetSelector);
                selectorByType[T] = selector;
            }
            return selector;
        }

        #endregion

        private static Func<IOrderedQueryable<Ts>, IOrderedQueryable<Td>> _selector;

        /// <summary>
        /// 获取该自定义类的选择器
        /// </summary>
        public static Func<IOrderedQueryable<Ts>, IOrderedQueryable<Td>> Selector
        {
            get
            {
                if (_selector == null) _selector = new Func<IOrderedQueryable<Ts>, IOrderedQueryable<Td>>((Activator.CreateInstance(typeof(Td)) as CustomEntity<Ts, Td>).GetSelector);
                return _selector;
            }
        }
    }

    #endregion

    #region 数据更新

    /// <summary>
    /// 更新模式
    /// </summary>
    public enum UpdateMode
    {
        /// <summary>
        /// 仅更新
        /// </summary>
        OnlyUpdate,

        /// <summary>
        /// 仅新增
        /// </summary>
        OnlyInsert,

        /// <summary>
        /// 新增或更新
        /// </summary>
        InsertOrUpdate,

        /// <summary>
        /// 删除
        /// </summary>
        Delete
    }

    /// <summary>
    /// 单条记录
    /// </summary>
    /// <typeparam name="TEntities"></typeparam>
    /// <typeparam name="TEntity"></typeparam>
    public abstract class RecordArgs<TEntities, TEntity> : DataClassBase<TEntities>
        where TEntity : new()
        where TEntities : ObjectContext
    {
        /// <summary>
        /// 得到记录
        /// </summary>
        /// <param name="container"></param>
        /// <returns></returns>
        public virtual TEntity GetRecord(TEntities container) { return default(TEntity); }

        /// <summary>
        /// 获取记录
        /// </summary>
        /// <returns></returns>
        public TEntity GetRecord()
        {
            using (var container = GetEntities())
            {
                return GetRecord(container);
            }
        }

        /// <summary>
        /// 得到插入后的记录
        /// </summary>
        /// <param name="container"></param>
        /// <returns></returns>
        public virtual TEntity CreateRecord(TEntities container) { return new TEntity(); }
    }

    /// <summary>
    /// 更新方法
    /// </summary>
    public abstract class UpdateClass<TEntities, TEntity> : RecordArgs<TEntities, TEntity>
        where TEntity : new()
        where TEntities : ObjectContext
    {
        /// <summary>
        /// 实体类型
        /// </summary>
        public Type EntityType { get { return typeof(TEntity); } }

        #region 缓存通知

        //缓存通知用于在更新操作发生时，用指定的键值来更新缓存帮助器

        /// <summary>
        /// 在派生类重写时以获取要通知更改的缓存帮助器
        /// </summary>
        public virtual ICacheHelper[] NotifyCacheHelpers { get { throw new NotImplementedException("请在派生类中重写此属性以获取要更新的缓存帮助器集合。"); } }

        /// <summary>
        /// 在派生类重写以获取要通知更改的缓存键
        /// </summary>
        /// <param name="record"></param>
        /// <returns></returns>
        public virtual string GetNotifyCacheKey(TEntity record) { throw new NotImplementedException("请在派生类中重写此属性以获取用来更新的缓存更新键。"); }

        /// <summary>
        /// 是否允许缓存通知，如果允许，应重写CacheHelpers属性和GetCacheKey方法
        /// </summary>
        public virtual bool EnableCacheNotify { get { return false; } }

        /// <summary>
        /// 执行缓存通知，向各个缓存帮助器发出通知
        /// </summary>
        /// <param name="record"></param>
        protected void CacheNotify(TEntity record)
        {
            if (!EnableCacheNotify) return;
            ICacheHelper[] helpers = NotifyCacheHelpers;
            if (helpers == null || helpers.Length == 0) return;
            string ck = GetNotifyCacheKey(record);
            foreach (ICacheHelper ch in helpers)
            {
                ch.NoticeChange(ck);
            }
            OnNotifyCache(record);
        }

        /// <summary>
        /// 在派生类中重写时，执行自定义缓存通知
        /// </summary>
        /// <param name="record"></param>
        public virtual void OnNotifyCache(TEntity record)
        {

        }

        #endregion

        /// <summary>
        /// 模式
        /// </summary>
        public virtual UpdateMode Mode
        {
            get;
            set;
        }

        /// <summary>
        /// 处理记录属性的函数(T)
        /// </summary>
        public Func<TEntity, bool> UpdateFunc
        {
            get;
            set;
        }
        /// <summary>
        /// 是否需要更新之后的新排序值
        /// </summary>
        public bool NeedNewIndex { get; set; }
        /// <summary>
        /// 更新/添加 之后的新排序值
        /// </summary>
        public int NewIndex
        {
            get;
            set;
        }
        /// <summary>
        /// 排序查询
        /// </summary>
        /// <param name="container"></param>
        /// <returns></returns>
        protected virtual IOrderedQueryable<TEntity> GetIndexQuery(TEntities container)
        {
            return null;
        }

        private TEntity _returnRecord;
        /// <summary>
        /// 上次操作过程中保存或删除的记录
        /// </summary>
        public TEntity ReturnRecord { get { return _returnRecord; } }

        /// <summary>
        /// 默认为物理删除，若要进行逻辑删除，请在派生类中重写
        /// </summary>
        /// <param name="container"></param>
        /// <param name="record"></param>
        /// <returns></returns>
        public virtual bool DeleteRecord(TEntities container, TEntity record)
        {
            container.DeleteObject(record);
            return true;
        }

        /// <summary>
        /// 当数据将要被插入时的自定义操作
        /// </summary>
        /// <param name="record"></param>
        public virtual bool OnInserting(TEntity record) { return true; }
        /// <summary>
        /// 当数据被插入后的自定义操作
        /// </summary>
        /// <param name="record"></param>
        public virtual void OnInserted(TEntity record) { }
        /// <summary>
        /// 当数据将要被更新时的自定义操作
        /// </summary>
        /// <param name="record"></param>
        public virtual bool OnUpdating(TEntity record) { return true; }
        /// <summary>
        /// 当数据被更新后的自定义操作
        /// </summary>
        /// <param name="record"></param>
        public virtual void OnUpdated(TEntity record) { }
        /// <summary>
        /// 当数据将要被删除时的自定义操作
        /// </summary>
        /// <param name="record"></param>
        public virtual bool OnDeleting(TEntity record) { return true; }
        /// <summary>
        /// 当数据被删除后的自定义操作
        /// </summary>
        /// <param name="record"></param>
        public virtual void OnDeleted(TEntity record) { }

        Dictionary<string, object> oldValues;

        /// <summary>
        /// 预处理更改通知
        /// </summary>
        /// <param name="oldrecord"></param>
        void PrepareUpdateNotify(TEntity oldrecord)
        {
            oldValues = EntityCacheHelper.Instance.GetOldValues(oldrecord);
        }

        /// <summary>
        /// 分析更改并执行更改通知
        /// </summary>
        /// <param name="newrecord"></param>
        void DoUpdateNotify(TEntity newrecord)
        {
            EntityCacheHelper.Instance.CompareValues(newrecord, oldValues);
            oldValues = null;
        }

        /// <summary>
        /// 在给定的上下文中依据已设置的配置对数据进行处理
        /// </summary>
        /// <param name="container"></param>
        /// <returns></returns>
        public bool Process(TEntities container)
        {
            return Process(container, true);
        }

        /// <summary>
        /// 在给定的上下文中依据已设置的配置对数据进行处理
        /// </summary>
        /// <param name="container"></param>
        /// <param name="saveChange">是否立刻保存结果，如果否，将必须手动执行container.SaveChanges。且无法立刻获取部分返回值（如NewIndex等），但缓存仍然被刷新。
        /// 注意：如果选是，将会提交container中自上次保存以来的所有更改。
        /// </param>
        /// <returns></returns>
        public bool Process(TEntities container, bool saveChange)
        {
            #region 删除处理
            if (Mode == UpdateMode.Delete)
            {
                _returnRecord = GetRecord(container);
                if (_returnRecord == null) return false;
                if (!OnDeleting(_returnRecord)) return false;
                DeleteRecord(container, _returnRecord);
                if (!saveChange || container.SaveChanges() > 0)
                {
                    CacheNotify(_returnRecord);
                    OnDeleted(_returnRecord);
                    return true;
                }
                else
                {
                    return false;
                }
            }
            #endregion

            bool isinsert = false;

            if (Mode == UpdateMode.OnlyInsert)
            {
                isinsert = true;
                _returnRecord = CreateRecord(container);
            }
            else if (Mode == UpdateMode.OnlyUpdate)
            {
                _returnRecord = GetRecord(container);
                if (_returnRecord == null) return false;
            }
            else
            {
                _returnRecord = GetRecord(container);
                if (_returnRecord == null)
                {
                    _returnRecord = CreateRecord(container);
                    isinsert = true;
                }
            }
            if (isinsert)
            {
                if (!OnInserting(_returnRecord)) return false;
            }
            else
            {
                if (!OnUpdating(_returnRecord)) return false;
            }
            if (_returnRecord == null || !UpdateFunc(_returnRecord)) return false;
            bool issucc = !saveChange || container.SaveChanges() >= 1;
            if (!issucc) return false;

            CacheNotify(_returnRecord);
            if (saveChange && NeedNewIndex)
            {
                var query = GetIndexQuery(container);
                NewIndex = query.Count();
            }
            if (isinsert)
            {
                OnInserted(_returnRecord);
            }
            else
            {
                OnUpdated(_returnRecord);
            }
            return true;
        }

        /// <summary>
        /// 依据已设置的配置对数据进行处理
        /// </summary>
        /// <returns></returns>
        public bool Process()
        {
            using (var container = GetEntities())
            {
                return Process(container);
            }
        }

        /// <summary>
        /// 将实体更新到数据库[未实现]
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool UpdateFromEntity(TEntity obj)
        {

            return false;
        }
    }

    /// <summary>
    /// 助手
    /// </summary>
    public class UpdateClassHelper
    {
        /// <summary>
        /// 将属性集转换为赋值函数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="properties"></param>
        /// <returns></returns>
        public static Func<T, bool> ConvertToUpdateFunc<T>(IDictionary properties)
        {
            return new Func<T, bool>(delegate(T obj)
            {
                var t = typeof(T);
                if (properties == null) return true;
                foreach (DictionaryEntry entry in properties)
                {
                    var p = t.GetProperty(entry.Key.ToString());
                    p.SetValue(obj, entry.Value, null);
                }
                return true;
            });
        }

        /// <summary>
        /// 创建一个复制用的函数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static Func<T, bool> ConvertToCopyFunc<T>(T source)
        {
            return new Func<T, bool>(delegate(T obj)
            {
                var t = typeof(T);
                var properties = t.GetProperties();
                foreach (var pinfo in properties)
                {
                    var value = pinfo.GetValue(source, null);
                    pinfo.SetValue(obj, value, null);
                }
                return true;
            });
        }
    }

    #endregion

}
